package algorithm;


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

public class Correlation {

	private HashMap<Float, Float> correlationHashmap;

	public Correlation(){

		correlationHashmap = new HashMap<Float, Float>();

	}

	public HashMap<Float, Float> calcCorrelation(List<Float> vroots, List<Float> votes, Connection conn ){
		try{
			int vrootCount = vroots.size();
			float AmeanVote = 0;
			for (int i=0; i<vrootCount; i++){
				AmeanVote = AmeanVote + votes.get(i);
			}
			AmeanVote = AmeanVote/(float)vrootCount;

			Statement stmt = conn.createStatement();
			Statement stmt2 = conn.createStatement();
			Statement stmt3 = conn.createStatement();
			ResultSet rs;
			ResultSet rs2;
			ResultSet rs3;

			String query1;
			String intermediateQuery = "";

			query1= "SELECT DISTINCT UserID FROM casebase WHERE Vroot = "+ vroots.get(0).toString();;

			for (int i=1; i<vrootCount; i++){
				intermediateQuery += " OR ";
				intermediateQuery += "Vroot = "+ vroots.get(i);
			}	 
			query1 += intermediateQuery;
			rs = stmt.executeQuery(query1);

			String query2;
			String query3;

			float AvoteDeviation;
			float IvoteDeviation;
			float SumAvoteDeviationSquare;
			float SumIvoteDeviationSquare;

			float numerator, denominator;
			float correlation;

			int tempUserId;

			while (rs.next())
			{
				tempUserId = rs.getInt("UserID");
				query2 = "SELECT * FROM casebase WHERE UserID = " + tempUserId 
				+ " AND (Vroot = " + vroots.get(0).toString() + intermediateQuery +")";
				query3 = "SELECT meanvote FROM meanvotes WHERE UserID = " + tempUserId;
				rs2 = stmt2.executeQuery(query2);
				rs3 = stmt3.executeQuery(query3);
				numerator = 0;
				denominator = 0;
				correlation = 0;
				SumAvoteDeviationSquare = 0;
				SumIvoteDeviationSquare = 0;
				float ImeanVote = 0;
				while(rs3.next()){
					ImeanVote = rs3.getFloat("meanvote");
				}


				while(rs2.next()){

					AvoteDeviation = votes.get(vroots.indexOf((float)rs2.getInt("Vroot"))) - AmeanVote;
					IvoteDeviation = (float) ((float)rs2.getInt("Votes") - ImeanVote );

					numerator += AvoteDeviation*IvoteDeviation;
					SumAvoteDeviationSquare += AvoteDeviation*AvoteDeviation;
					SumIvoteDeviationSquare += IvoteDeviation*IvoteDeviation;

				}
				denominator = (float) Math.sqrt(SumAvoteDeviationSquare*SumIvoteDeviationSquare);
				if(denominator == 0)
					correlation = 0;
				else correlation = numerator/denominator;

				correlationHashmap.put((float)tempUserId, correlation);

			}



		}catch(Exception e){
			e.printStackTrace();
		}
		return correlationHashmap;

	}

	public static float CalculateVote(HashMap<Float, Float> correlations, int vroot){
		
		float k, sum;
		sum = 0;
		
		for(Float weight: correlations.values()){
			sum += Math.abs(weight);
		}
		
		k = 1 / sum;
		
		try {
			Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
			String filename = "C:/zeus.mdb";
			String database = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=";
			database+= filename.trim() + ";DriverID=22;READONLY=true}";
			Connection con = DriverManager.getConnection(database ,"","");
			
			Statement stmt = con.createStatement();
			
			String meanVoteQuery = "SELECT meanvote FROM meanvotes WHERE UserID = 10001";
			ResultSet meanVoteResult = stmt.executeQuery(meanVoteQuery);
			meanVoteResult.next();
			
			float vaBar = meanVoteResult.getFloat("meanvote");						
						
			Float paj = new Float(0.0);			
			
			for(Float userID: correlations.keySet()){
				Integer user = userID.intValue();
				
				String voteQuery = "SELECT Votes FROM casebase WHERE UserID = " + user.toString() + " AND Vroot = " + vroot;
				ResultSet voteResult = stmt.executeQuery(voteQuery);
				voteResult.next();
				
				int vij;
				
				try{
					vij = voteResult.getInt("Votes");
				}
				catch(SQLException s){
					vij = 0;
				}
				
				String meanVoteQuery2 = "SELECT meanvote FROM meanvotes WHERE UserID = " + user.toString();
				ResultSet meanVoteResult2 = stmt.executeQuery(meanVoteQuery2);
				meanVoteResult2.next();
				
				int viBar = meanVoteResult2.getInt("meanvote");								
				
				paj += correlations.get(userID) * (vij - viBar);
				
			}
			
			paj *= k;
			paj += vaBar;
			
			con.close();
			
			return paj;
								
		
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}				
		
		return 0;
		
	}


	public static void main(String[] args) {
		try {

			Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
			String filename = "C:/zeus.mdb";
			String database = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=";
			database+= filename.trim() + ";DriverID=22;READONLY=true}";
			Connection con = DriverManager.getConnection(database ,"","");

			Correlation calculateCorr = new Correlation();

			List<Float> vroots =new ArrayList<Float>();
			List<Float> votes = new ArrayList<Float>();

			vroots.add((float)1000);
			votes.add((float)9);
			vroots.add((float)1001);
			votes.add((float)14);

			HashMap<Float,Float> correlations = calculateCorr.calcCorrelation(vroots, votes, con);

			System.out.println(correlations.size());
			Iterator iterator = correlations.entrySet().iterator();
			while( iterator. hasNext() ){
				System.out.println( iterator.next() );
			}
			
			con.close();
			
			ArrayList<Float> predictedVotes = new ArrayList<Float>();
			
			for(int i = 1000; i <= 1295; i++){
				Float vote = Correlation.CalculateVote(correlations, i);
				predictedVotes.add(vote);
				System.out.println(vote);
			}
						
			

		}catch(Exception e){
			e.printStackTrace();
		}
	}

}
